package com.zg.handler;

import com.zg.CliemtManage.ClientInfo;
import com.zg.callback.BootMqttMsgBack;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.mqtt.MqttFixedHeader;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class MqttMsgInboundHandler extends ChannelInboundHandlerAdapter {

    private ClientInfo clientInfo = new ClientInfo();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof MqttMessage){
            MqttMessage mqttMessage = (MqttMessage)msg;
            log.info("接收到消息：{}",mqttMessage);
            MqttFixedHeader mqttFixedHeader = mqttMessage.fixedHeader();
            MqttMessageType mqttMessageType = mqttFixedHeader.messageType();//请求行为
//            log.info("接收到消息，行为：{},\n qos：{}，\n 负载类容：{}",mqttMessageType,mqttFixedHeader.qosLevel(),mqttMessage.payload());

            Channel channel = ctx.channel();

            //连接消息处理
            if (mqttMessageType.equals(MqttMessageType.CONNECT)){
                BootMqttMsgBack.connack(channel,mqttMessage);
            }
            switch (mqttMessageType){
                case PUBLISH:		//	客户端发布消息
                    //	PUBACK报文是对QoS 1等级的PUBLISH报文的响应
                    System.out.println("客户端发布消息");
                    BootMqttMsgBack.puback(channel, mqttMessage);
                    break;
                case PUBREL:		//	发布释放
                    //	PUBREL报文是对PUBREC报文的响应
                    //	to do
                    BootMqttMsgBack.pubcomp(channel, mqttMessage);
                    break;
                case SUBSCRIBE:		//	客户端订阅主题
                    //	客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅，每个订阅注册客户端关心的一个或多个主题。
                    //	为了将应用消息转发给与那些订阅匹配的主题，服务端发送PUBLISH报文给客户端。
                    //	SUBSCRIBE报文也（为每个订阅）指定了最大的QoS等级，服务端根据这个发送应用消息给客户端
                    // 	to do
                    BootMqttMsgBack.suback(channel, mqttMessage);
                    break;
                case UNSUBSCRIBE:	//	客户端取消订阅
                    //	客户端发送UNSUBSCRIBE报文给服务端，用于取消订阅主题
                    //	to do
                    BootMqttMsgBack.unsuback(channel, mqttMessage);
                    break;
                case PINGREQ:		//	客户端发起心跳
                    //	客户端发送PINGREQ报文给服务端的
                    //	在没有任何其它控制报文从客户端发给服务的时，告知服务端客户端还活着
                    //	请求服务端发送 响应确认它还活着，使用网络以确认网络连接没有断开
                    BootMqttMsgBack.pingresp(channel, mqttMessage);
                    break;
                case DISCONNECT:	//	客户端主动断开连接
                    //	DISCONNECT报文是客户端发给服务端的最后一个控制报文， 服务端必须验证所有的保留位都被设置为0
                    //	to do
                    BootMqttMsgBack.disConnect(channel,mqttMessage);
                    break;
                default:
                    break;
            }
        }

    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        Channel channel = ctx.channel();
        clientInfo.client_shutdown(channel);
        log.error("channel发生异常:{},原因：{}",channel,cause);
    }
}
